package router

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

type FileHandler struct {
}

func NewFileHandler() *FileHandler {
	return &FileHandler{}
}

func (handler *FileHandler) RegisterRoutes(r *gin.RouterGroup) {
	r.GET("/file/download", handler.FileDownload)
	r.POST("/file/upload", handler.FileUpload)
}

func (p *FileHandler) FileDownload(ctx *gin.Context) {
	filename := ctx.Query("filename")

	path := "uploads/" + filename
	if !isPathSafe(path) {
		ctx.String(http.StatusBadRequest, "Invalid path")
		return
	}

	// 设置响应头
	ctx.Header("Content-Description", "File Transfer")
	ctx.Header("Content-Type", "application/octet-stream")
	ctx.Header("Content-Disposition", "attachment; filename=" + filename)
	ctx.Header("Content-Transfer-Encoding", "binary")
	ctx.Header("Expires", "0")
	ctx.Header("Cache-Control", "must-revalidate")
	ctx.Header("Pragma", "public")

	ctx.File(path)
	return
}

func (p *FileHandler) FileUpload(ctx *gin.Context) {
	// 获取上传的文件
	file, header, err := ctx.Request.FormFile("file")
	if err != nil {
		ctx.String(http.StatusBadRequest, fmt.Sprintf("上传文件失败: %s", err.Error()))
		return
	}
	defer file.Close()

	// 获取文件的 MIME 类型
	contentType := header.Header.Get("Content-Type")
	// 获取文件名
	filename := header.Filename

	// 检查文件类型是否为图片
	if !isImage(contentType) {
		ctx.String(http.StatusBadRequest, "只允许上传图片文件")
		return
	}

	// 获取文件扩展名
	ext := filepath.Ext(filename)

	// 检查文件扩展名是否为图片
	if !isImageExt(ext) {
		ctx.String(http.StatusBadRequest, "只允许上传图片文件")
		return
	}

	// 创建目标文件
	out, err := os.Create("uploads/" + filename)
	if err != nil {
		ctx.String(http.StatusInternalServerError, fmt.Sprintf("创建文件失败: %s", err.Error()))
		return
	}
	defer out.Close()

	// 将上传的文件内容写入目标文件
	_, err = io.Copy(out, file)
	if err != nil {
		ctx.String(http.StatusInternalServerError, fmt.Sprintf("写入文件失败: %s", err.Error()))
		return
	}
}

// isImage 检查文件类型是否为图片
func isImage(contentType string) bool {
	switch contentType {
	case "image/jpeg", "image/png", "image/gif", "image/bmp", "image/tiff", "image/webp":
		return true
	default:
		return false
	}
}

// isImageExt 检查文件扩展名是否为图片
func isImageExt(ext string) bool {
	switch ext {
	case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp":
		return true
	default:
		return false
	}
}

func isPathSafe(path string) bool {
	// 检查 path 中是否包含 "./" 或 "../" 或 "%"
	if strings.Contains(path, "./") || strings.Contains(path, "../") || strings.Contains(path, "%") {
		return false
	}
	return true
}